package net.oschina.allchat.server.framework.core.internal.config;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.Reader;
import java.util.Properties;
import java.util.StringTokenizer;

import net.oschina.allchat.server.framework.core.commons.utils.IoUtils;
import net.oschina.allchat.server.framework.core.config.IApplicationConfiguration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class ApplicationConfiguration implements IApplicationConfiguration {
	private static final Logger logger = LoggerFactory.getLogger(ApplicationConfiguration.class);
	
	private static final String NAME_APPLICATION_CONFIG_FILE = "application.ini";
	
	private static final String CONFIG_KEY_DISABLED_SERVICES = "disabled.services";
	private static final String CONFIG_KEY_IP = "ip";
	private static final String CONFIG_KEY_DOMAIN_NAME = "domain.name";
	private static final String CONFIG_KEY_CONFIGURATION_MANAGER_CLASS = "configuration.manager.class";
	private static final String CONFIG_KEY_CONFIGURATION_MANAGER_BUNDLE_SYMBOLIC_NAME = "configuration.manager.bundle.symbolic.name";
	private static final String CONFIG_KEY_COMPONENT_BINDING_PROFILE = "component.binding.profile";
	private static final String CONFIG_KEY_LOG_CONFIGURATION_FILE = "log.configuration.file";
	
	private String domainName = "localhost";
	private String ip = "127.0.0.1";
	private String[] disabledServices = new String[0];
	private String componentBindingProfile = "${config.dir}/component-binding.ini";
	private String logConfigurationFile;
	
	private String appHome;
	private String configDir;
	private String configurationManagerBundleSymbolicName;
	private String configurationManagerClass;
	
	public ApplicationConfiguration(String appHome, String configDir) {
		this.appHome = appHome;
		this.configDir = configDir;
		
		merge(getAppConfigFile(configDir));
	}
	
	private File getAppConfigFile(String configDir) {
		File appConfigFile = new File(configDir, NAME_APPLICATION_CONFIG_FILE);
		if (appConfigFile.exists() && appConfigFile.isFile())
			return appConfigFile;
		
		return null;
	}

	@Override
	public String getIp() {
		return ip;
	}

	@Override
	public String getConfigurationManagerBundleSymbolicName() {
		return configurationManagerBundleSymbolicName;
	}

	@Override
	public String getConfigurationManagerClass() {
		return configurationManagerClass;
	}

	@Override
	public String[] getDisabledServices() {
		return disabledServices;
	}

	@Override
	public String getAppHome() {
		return appHome;
	}

	private void merge(File configFile) {
		if (configFile == null)
			return;

		Properties properties = new Properties();
		Reader reader = null;
		
		try {
			reader = new BufferedReader(new FileReader(configFile));
			properties.load(reader);
			
			for (Object key : properties.keySet()) {
				if (CONFIG_KEY_CONFIGURATION_MANAGER_BUNDLE_SYMBOLIC_NAME.equals(key)) {
					configurationManagerBundleSymbolicName = properties.getProperty((String)key);
				} else if (CONFIG_KEY_CONFIGURATION_MANAGER_CLASS.equals(key)) {
					configurationManagerClass = properties.getProperty((String)key);
				} else if (CONFIG_KEY_DOMAIN_NAME.equals(key)) {
					domainName = properties.getProperty((String)key);
				} else if (CONFIG_KEY_IP.equals(key)) {
					ip = properties.getProperty((String)key);
				} else if (CONFIG_KEY_DISABLED_SERVICES.equals(key)) {
					setDisabledServices(properties.getProperty((String)key));
				} else if (CONFIG_KEY_COMPONENT_BINDING_PROFILE.equals(key)) {
					componentBindingProfile = properties.getProperty((String)key);
				} else if (CONFIG_KEY_LOG_CONFIGURATION_FILE.equals(key)) {
					logConfigurationFile = properties.getProperty((String)key);
				} else {
					// ignore
					if (logger.isWarnEnabled()) {
						logger.warn(String.format("unknown application configuration item: '%s;", key));
					}
				}
			}
		} catch (Exception e) {
			// do nothing
		} finally {
			IoUtils.closeIO(reader);
		}
	}
	
	private String replacePathVariables(String value) {
		value = value.replace("${config.dir}", configDir);
		value = value.replace("${user.home}", System.getProperty("user.home"));
		
		return value;
	}

	private void setDisabledServices(String sDisabledServices) {
		StringTokenizer tokenizer = new StringTokenizer(sDisabledServices, ",");
		disabledServices = new String[tokenizer.countTokens()];
		int i = 0;
		while (tokenizer.hasMoreTokens()) {
			disabledServices[i] = tokenizer.nextToken().trim();
			i++;
		}
	}

	@Override
	public String getDomainName() {
		return domainName;
	}

	@Override
	public String getComponentBindingProfile() {
		return replacePathVariables(componentBindingProfile);
	}
	
	public void setComponentBindingProfile(String componentBindingProfile) {
		this.componentBindingProfile = componentBindingProfile;
	}

	@Override
	public String getConfigDir() {
		return configDir;
	}

	@Override
	public String getLogConfigurationFile() {
		if (logConfigurationFile == null)
			return null;
		
		return replacePathVariables(logConfigurationFile);
	}
}
